home *** CD-ROM | disk | FTP | other *** search
/ IRIX 6.2 Applications 1996 May / SGI IRIX 6.2 Applications 1996 May.iso / dist / impr_dev.idb / usr / impressario / src / libimp / impRowIO.c.z / impRowIO.c
C/C++ Source or Header  |  1996-05-06  |  21KB  |  747 lines

  1. /**************************************************************************
  2.  *
  3.  *           Copyright (c)    1993 Silicon Graphics, Inc.
  4.  *            All Rights Reserved
  5.  *
  6.  *       THIS    IS UNPUBLISHED PROPRIETARY SOURCE CODE OF SGI
  7.  *
  8.  * The copyright notice above does not evidence any actual of intended
  9.  * publication of such source code, and is an unpublished work by Silicon
  10.  * Graphics, Inc. This material contains CONFIDENTIAL INFORMATION that is
  11.  * the property of Silicon Graphics, Inc. Any use, duplication or
  12.  * disclosure not specifically authorized by Silicon Graphics is strictly
  13.  * prohibited.
  14.  *
  15.  * RESTRICTED RIGHTS LEGEND:
  16.  *
  17.  * Use, duplication or disclosure by the Government is subject to
  18.  * restrictions as set forth in subdivision (c)(1)(ii) of the Rights in
  19.  * Technical Data and Computer Software clause at DFARS 52.227-7013,
  20.  * and/or in similar or successor clauses in the FAR, DOD or NASA FAR
  21.  * Supplement. Unpublished - rights reserved under the Copyright Laws of
  22.  * the United States. Contractor is SILICON GRAPHICS, INC., 2011 N.
  23.  * Shoreline Blvd., Mountain View, CA 94039-7311
  24.  **************************************************************************
  25.  *
  26.  * File: impRowIO.c
  27.  *
  28.  * Description: Image row read and write routines.
  29.  *
  30.  **************************************************************************/
  31.  
  32.  
  33. #ident "$Revision: 1.6 $"
  34.  
  35.  
  36. #include <stdio.h>
  37. #include <sys/types.h>
  38. #include <assert.h>
  39. #include "impI.h"
  40.  
  41.  
  42. /* Local functions */
  43.  
  44. static int rleGetRowSize(IMPImage *image, ushort_t row, ushort_t channel);
  45. static int rleSetRowSize(IMPImage *image, long count, ushort_t row,
  46.                             ushort_t channel);
  47. static void rleExpandRow(short *rleBuf, int ibpp, short *expBuf, int obpp);
  48. static int rleCompactRow(short *expBuf, int ibpp, short *rleBuf, int obpp,
  49.                             int npixels);
  50.  
  51.  
  52. /**************************************************************************
  53.  *
  54.  * Function: impWriteRow
  55.  *
  56.  * Description: Writes the specified image data as the specified row and
  57.  *    channel.
  58.  *
  59.  * Parameters: 
  60.  *    image (I) - image to write
  61.  *    buffer (I) - data to write
  62.  *    row (I) - image row to write
  63.  *    channel (I) - image channel to write
  64.  *
  65.  * Return: Number of pixels written if no error. -1 and IMPerrno set if
  66.  *    errors.
  67.  *
  68.  **************************************************************************/
  69.  
  70. int impWriteRow(IMPImage *image, short *buffer, ushort_t row, ushort_t channel) {
  71.     register long vmin, vmax;
  72.     register ushort_t x;
  73.     register short *sptr;
  74.     int count, retv;
  75.  
  76.     /*
  77.      * Sanity check the inputs
  78.      */
  79.     assert(image != NULL);
  80.     assert(buffer != NULL);
  81.  
  82.     /*
  83.      * Verify we can write image
  84.      */
  85.     if (!_impWriting(image))
  86.     _impReturnError(IMP_ERR_WRITEFLAG);
  87.  
  88.     /*
  89.      * Use image dimension to sanitize the row and channel values
  90.      */
  91.     if (impDimension(image) < 3)
  92.     channel = 0;
  93.     if (impDimension(image) < 2)
  94.     row = 0;
  95.  
  96.     /*
  97.      * Determine the min and max image data values. Note that
  98.      * for 1 BPP we are packing the data as uchar into tmpbuf.
  99.      * We can just write this for the 1 BPP VERBATIM case.
  100.      */
  101.     vmin = impMinValue(image);
  102.     vmax = impMaxValue(image);
  103.     sptr = buffer;
  104.     switch (impRasterBPP(image)) {
  105.     case 1:
  106.         {
  107.             register uchar_t *cptr = (uchar_t*)image->tmpbuf;
  108.             for (x = impXSize(image); x--; ) {
  109.             *cptr = (uchar_t)(*sptr++);
  110.             /* LINTED */
  111.             if (*cptr > vmax) vmax = *cptr;
  112.             /* LINTED */
  113.             if (*cptr < vmin) vmin = *cptr;
  114.             cptr++;
  115.             }
  116.         }
  117.         break;
  118.     case 2:
  119.         for (x = impXSize(image); x--; ) {
  120.         /* LINTED */
  121.             if ((unsigned short)*sptr > vmax)
  122.             vmax = (unsigned short)*sptr;
  123.         /* LINTED */
  124.             if ((unsigned short)*sptr < vmin)
  125.             vmin = (unsigned short)*sptr;
  126.             sptr++;
  127.         }
  128.         break;
  129.     default:
  130.         _impReturnError(IMP_ERR_BADBPP);
  131.     }
  132.     impMinValue(image) = vmin;
  133.     impMaxValue(image) = vmax;
  134.  
  135.     /*
  136.      * Go to the appropriate position in the file and
  137.      * write the image data according to its raster encoding
  138.      * and bytes per pixel
  139.      */
  140.     if (impIsVERBATIM(image)) {
  141.         if (_impSeekRow(image, row, channel) < 0)
  142.         _impReturnError(IMPerrno);
  143.     switch (impRasterBPP(image)) {
  144.         case 1:
  145.         if ((retv = _impWrite(image, image->tmpbuf, impXSize(image)))
  146.                             != impXSize(image))
  147.             _impReturnError((retv < 0)? IMPerrno: IMP_ERR_SHORTWRITE);
  148.         return impXSize(image);
  149.         case 2:
  150.         count = impXSize(image) << 1;
  151.         if (image->dorev)
  152.             _impSwapShorts((ushort_t*)buffer, count);
  153.         retv = _impWrite(image, buffer, count);
  154.         if (image->dorev)
  155.             _impSwapShorts((ushort_t*)buffer, count);
  156.         if (retv != count)
  157.             _impReturnError((retv < 0)? IMPerrno: IMP_ERR_SHORTWRITE);
  158.         return impXSize(image);
  159.     }
  160.     } else if (impIsRLE(image)) {
  161.     switch (impRasterBPP(image)) {
  162.         case 1:
  163.         count = rleCompactRow(buffer, 2, image->tmpbuf, 1,
  164.                             impXSize(image));
  165.         if (rleSetRowSize(image, count, row, channel) < 0)
  166.             _impReturnError(IMPerrno);
  167.             if (_impSeekRow(image, row, channel) < 0)
  168.                 _impReturnError(IMPerrno);
  169.         if ((retv = _impWrite(image, image->tmpbuf, count)) != count)
  170.             _impReturnError((retv < 0)? IMPerrno: IMP_ERR_SHORTWRITE);
  171.         return impXSize(image);
  172.         case 2:
  173.         count = rleCompactRow(buffer, 2, image->tmpbuf, 2,
  174.                             impXSize(image)) << 1;
  175.         if (rleSetRowSize(image, count, row, channel) < 0)
  176.             _impReturnError(IMPerrno);
  177.             if (_impSeekRow(image, row, channel) < 0)
  178.                 _impReturnError(IMPerrno);
  179.         if (image->dorev)
  180.             _impSwapShorts((ushort_t*)image->tmpbuf, count);
  181.         retv = _impWrite(image, image->tmpbuf, count);
  182.         if (image->dorev)
  183.             _impSwapShorts((ushort_t*)image->tmpbuf, count);
  184.         if (retv != count)
  185.             _impReturnError((retv < 0)? IMPerrno: IMP_ERR_SHORTWRITE);
  186.         return impXSize(image);
  187.     }
  188.     }
  189.  
  190.     _impReturnError(IMP_ERR_BADIMAGE);
  191. }
  192.  
  193.  
  194. /**************************************************************************
  195.  *
  196.  * Function: impWriteRowB
  197.  *
  198.  * Description: Writes the specified image data as the specified row and
  199.  *    channel. The data buffer for this function is of type unsigned
  200.  *    char. This eliminates the need to do copying for 1 BPP images.
  201.  *    Note that the image must be 1 BPP or an error is returned.
  202.  *
  203.  * Parameters: 
  204.  *    image (I) - image to write
  205.  *    buffer (I) - data to write
  206.  *    row (I) - image row to write
  207.  *    channel (I) - image channel to write
  208.  *
  209.  * Return: Number of pixels written if no error. -1 and IMPerrno set if
  210.  *    errors.
  211.  *
  212.  **************************************************************************/
  213.  
  214. int impWriteRowB(IMPImage *image, uchar_t *buffer, ushort_t row,
  215.                             ushort_t channel)
  216. {
  217.     register long vmin, vmax;
  218.     register ushort_t x;
  219.     register uchar_t *cptr;
  220.     int count, retv;
  221.  
  222.     /*
  223.      * Sanity check the inputs
  224.      */
  225.     assert(image != NULL);
  226.     assert(buffer != NULL);
  227.  
  228.     /*
  229.      * Verify that the image is 1 BPP
  230.      */
  231.     if (impRasterBPP(image) != IMP_RASTER_BPP1)
  232.     _impReturnError(IMP_ERR_BADBPP);
  233.  
  234.     /*
  235.      * Verify we can write image
  236.      */
  237.     if (!_impWriting(image))
  238.     _impReturnError(IMP_ERR_WRITEFLAG);
  239.  
  240.     /*
  241.      * Use image dimension to sanitize the row and channel values
  242.      */
  243.     if (impDimension(image) < 3)
  244.     channel = 0;
  245.     if (impDimension(image) < 2)
  246.     row = 0;
  247.  
  248.     /*
  249.      * Determine the min and max image data values.
  250.      */
  251.     vmin = impMinValue(image);
  252.     vmax = impMaxValue(image);
  253.     for (x = impXSize(image), cptr = buffer; x--; cptr++) {
  254.     /* LINTED */
  255.         if (*cptr > vmax) vmax = *cptr;
  256.     /* LINTED */
  257.     if (*cptr < vmin) vmin = *cptr;
  258.     }
  259.     impMinValue(image) = vmin;
  260.     impMaxValue(image) = vmax;
  261.  
  262.     /*
  263.      * Go to the appropriate position in the file and
  264.      * write the image data according to its raster encoding
  265.      * and bytes per pixel
  266.      */
  267.     if (impIsVERBATIM(image)) {
  268.         if (_impSeekRow(image, row, channel) < 0)
  269.         _impReturnError(IMPerrno);
  270.     if ((retv = _impWrite(image, buffer, impXSize(image)))
  271.                             != impXSize(image))
  272.         _impReturnError((retv < 0)? IMPerrno: IMP_ERR_SHORTWRITE);
  273.     return impXSize(image);
  274.     } else if (impIsRLE(image)) {
  275.     /* LINTED */
  276.     count = rleCompactRow((short*)buffer, 1, image->tmpbuf, 1,
  277.                             impXSize(image));
  278.     if (rleSetRowSize(image, count, row, channel) < 0)
  279.         _impReturnError(IMPerrno);
  280.            if (_impSeekRow(image, row, channel) < 0)
  281.             _impReturnError(IMPerrno);
  282.     if ((retv = _impWrite(image, image->tmpbuf, count)) != count)
  283.         _impReturnError((retv < 0)? IMPerrno: IMP_ERR_SHORTWRITE);
  284.     return impXSize(image);
  285.     }
  286.  
  287.     _impReturnError(IMP_ERR_BADIMAGE);
  288. }
  289.  
  290.  
  291. /**************************************************************************
  292.  *
  293.  * Function: impReadRow
  294.  *
  295.  * Description: Reads the specified image data as the specified row and
  296.  *    channel.
  297.  *
  298.  * Parameters: 
  299.  *    image (I) - image to read
  300.  *    buffer (I) - data to read
  301.  *    row (I) - image row to read
  302.  *    channel (I) - image channel to read
  303.  *
  304.  * Return: Number of pixels read if no error. -1 and IMPerrno set if
  305.  *    errors.
  306.  *
  307.  **************************************************************************/
  308.  
  309. int impReadRow(IMPImage *image, short *buffer, ushort_t row, ushort_t channel)
  310. {
  311.     register int count, retv;
  312.  
  313.     /*
  314.      * Sanity check the inputs
  315.      */
  316.     assert(image != NULL);
  317.     assert(buffer != NULL);
  318.  
  319.     /*
  320.      * Verify we can read image
  321.      */
  322.     if (!_impReading(image))
  323.     _impReturnError(IMP_ERR_READFLAG);
  324.  
  325.     /*
  326.      * Use image dimension to sanitize the row and channel values
  327.      */
  328.     if (impDimension(image) < 3)
  329.     channel = 0;
  330.     if (impDimension(image) < 2)
  331.     row = 0;
  332.  
  333.     /*
  334.      * Seek to the specified row and channel and
  335.      * read the image data.
  336.      */
  337.     if (_impSeekRow(image, row, channel) < 0)
  338.     _impReturnError(IMPerrno);
  339.     if (impIsVERBATIM(image)) {
  340.     switch (impRasterBPP(image)) {
  341.         case 1:
  342.         if ((retv = _impRead(image, image->tmpbuf, impXSize(image)))
  343.                         != impXSize(image)) {
  344.             _impReturnError((retv < 0)? IMPerrno: IMP_ERR_SHORTREAD);
  345.         } else {
  346.             register uchar_t *cptr = (uchar_t*)image->tmpbuf;
  347.             register short *sptr = buffer;
  348.             register int i;
  349.             for (i = impXSize(image); i--;)
  350.                 *sptr++ = *cptr++;
  351.         }
  352.         return impXSize(image);
  353.         case 2:
  354.         count = impXSize(image) << 1;
  355.         if ((retv = _impRead(image, buffer, count)) != count)
  356.             _impReturnError((retv < 0)? IMPerrno: IMP_ERR_SHORTREAD);
  357.         if (image->dorev)
  358.             _impSwapShorts((ushort_t*)buffer, count);
  359.         return impXSize(image);
  360.         default:
  361.         _impReturnError(IMP_ERR_BADBPP);
  362.     }
  363.     }
  364.     else if (impIsRLE(image)) {
  365.     switch (impRasterBPP(image)) {
  366.         case 1:
  367.         if ((count = rleGetRowSize(image, row, channel)) < 0)
  368.             _impReturnError(IMPerrno);
  369.         if ((retv = _impRead(image, image->tmpbuf, count)) != count)
  370.             _impReturnError((retv < 0)? IMPerrno: IMP_ERR_SHORTREAD);
  371.         rleExpandRow(image->tmpbuf, 1, buffer, 2);
  372.         return impXSize(image);
  373.         case 2:
  374.         if ((count = rleGetRowSize(image, row, channel)) < 0)
  375.             _impReturnError(IMPerrno);
  376.         if ((retv = _impRead(image, image->tmpbuf, count)) != count)
  377.             _impReturnError((retv < 0)? IMPerrno: IMP_ERR_SHORTREAD);
  378.         if (image->dorev)
  379.             _impSwapShorts((ushort_t*)image->tmpbuf, count);
  380.         rleExpandRow(image->tmpbuf, 2, buffer, 2);
  381.         return impXSize(image);
  382.         default:
  383.         _impReturnError(IMP_ERR_BADBPP);
  384.     }
  385.     }
  386.  
  387.     _impReturnError(IMP_ERR_BADIMAGE);
  388. }
  389.  
  390.  
  391. /**************************************************************************
  392.  *
  393.  * Function: impReadRowB
  394.  *
  395.  * Description: Reads the specified image data as the specified row and
  396.  *    channel. The data buffer for this function is of type unsigned
  397.  *    char. This eliminates the need to do copying for 1 BPP images.
  398.  *    Note that the image must be 1 BPP or an error is returned.
  399.  *
  400.  * Parameters: 
  401.  *    image (I) - image to read
  402.  *    buffer (I) - data to read
  403.  *    row (I) - image row to read
  404.  *    channel (I) - image channel to read
  405.  *
  406.  * Return: Number of pixels read if no error. -1 and IMPerrno set if
  407.  *    errors.
  408.  *
  409.  **************************************************************************/
  410.  
  411. int impReadRowB(IMPImage *image, uchar_t *buffer, ushort_t row,
  412.                             ushort_t channel)
  413. {
  414.     register int count, retv;
  415.  
  416.     /*
  417.      * Sanity check the inputs
  418.      */
  419.     assert(image != NULL);
  420.     assert(buffer != NULL);
  421.  
  422.     /*
  423.      * Verify that the image is 1 BPP
  424.      */
  425.     if (impRasterBPP(image) != IMP_RASTER_BPP1)
  426.     _impReturnError(IMP_ERR_BADBPP);
  427.  
  428.     /*
  429.      * Verify we can read image
  430.      */
  431.     if (!_impReading(image))
  432.     _impReturnError(IMP_ERR_READFLAG);
  433.  
  434.     /*
  435.      * Use image dimension to sanitize the row and channel values
  436.      */
  437.     if (impDimension(image) < 3)
  438.     channel = 0;
  439.     if (impDimension(image) < 2)
  440.     row = 0;
  441.  
  442.     /*
  443.      * Seek to the specified row and channel and
  444.      * read the image data.
  445.      */
  446.     if (_impSeekRow(image, row, channel) < 0)
  447.     _impReturnError(IMPerrno);
  448.     if (impIsVERBATIM(image)) {
  449.     if ((retv = _impRead(image, buffer, impXSize(image)))
  450.                             != impXSize(image)) {
  451.         _impReturnError((retv < 0)? IMPerrno: IMP_ERR_SHORTREAD);
  452.     }
  453.     return impXSize(image);
  454.     }
  455.     else if (impIsRLE(image)) {
  456.     if ((count = rleGetRowSize(image, row, channel)) < 0)
  457.         _impReturnError(IMPerrno);
  458.     if ((retv = _impRead(image, image->tmpbuf, count)) != count)
  459.         _impReturnError((retv < 0)? IMPerrno: IMP_ERR_SHORTREAD);
  460.     /* LINTED */
  461.     rleExpandRow(image->tmpbuf, 1, (short*)buffer, 1);
  462.     return impXSize(image);
  463.     }
  464.  
  465.     _impReturnError(IMP_ERR_BADIMAGE);
  466. }
  467.  
  468.  
  469. /*
  470.  =========================================================================
  471.             LOCAL FUNCTIONS
  472.  =========================================================================
  473. */
  474.  
  475.  
  476. /**************************************************************************
  477.  *
  478.  * Function: rleGetRowSize
  479.  *
  480.  * Description: Returns the number of bytes in the RLE compressed row
  481.  *    for the row and channel specified.
  482.  *
  483.  * Parameters: 
  484.  *    image (I) - image file
  485.  *    row (I) - row whose size is desired
  486.  *    channel (I) - channel for the row
  487.  *
  488.  * Return: Row size in bytes if no error. -1 and IMPerrno set if error.
  489.  *
  490.  **************************************************************************/
  491.  
  492. static int rleGetRowSize(IMPImage *image, ushort_t row, ushort_t channel)
  493. {
  494.     /*
  495.      * Validate the row and channel inputs
  496.      */
  497.     if (_impBadRow(image, row, channel))
  498.     _impReturnError(IMP_ERR_BADROW);
  499.  
  500.     switch (impDimension(image)) {
  501.     case 1:
  502.         return image->rowsize[0];
  503.     case 2:
  504.         return image->rowsize[row];
  505.     case 3:
  506.         return image->rowsize[row + channel * impYSize(image)];
  507.     default:
  508.         break;
  509.     }
  510.  
  511.     _impReturnError(IMP_ERR_BADDIM);
  512. }
  513.  
  514.  
  515. /**************************************************************************
  516.  *
  517.  * Function: rleSetRowSize
  518.  *
  519.  * Description: Sets the number of bytes in the RLE compressed row
  520.  *    for the row and channel specified in the appropriate header
  521.  *    tables.
  522.  *
  523.  * Parameters: 
  524.  *    image (I) - image file
  525.  *    count (I) - RLE row size in bytes
  526.  *    row (I) - row whose size is to be set
  527.  *    channel (I) - channel for the row
  528.  *
  529.  * Return: 0 if no error. -1 and IMPerrno set if error.
  530.  *
  531.  **************************************************************************/
  532.  
  533. static int rleSetRowSize(IMPImage *image, long count, ushort_t row,
  534.                             ushort_t channel)
  535. {
  536.     __int32_t *sizeptr;
  537.  
  538.     /*
  539.      * Validate the row and channel inputs
  540.      */
  541.     if (_impBadRow(image, row, channel))
  542.     _impReturnError(IMP_ERR_BADROW);
  543.  
  544.     switch (impDimension(image)) {
  545.     case 1:
  546.         sizeptr = &image->rowsize[0];
  547.         image->rowstart[0] = image->rleend;
  548.         break;
  549.     case 2:
  550.         sizeptr = &image->rowsize[row];
  551.         image->rowstart[row] = image->rleend;
  552.         break;
  553.     case 3:
  554.         sizeptr = &image->rowsize[row + channel * impYSize(image)];
  555.         image->rowstart[row + channel * impYSize(image)] = image->rleend;
  556.         break;
  557.     default:
  558.             _impReturnError(IMP_ERR_BADDIM);
  559.     }
  560.     if (*sizeptr != -1)
  561.     image->wastebytes += *sizeptr;
  562.     *sizeptr = count;
  563.     image->rleend += count;
  564.  
  565.     return 0;
  566. }
  567.  
  568.  
  569. /**************************************************************************
  570.  *
  571.  * Function: rleExpandRow
  572.  *
  573.  * Description: Performs an adaptive RLE expansion on the specified data.
  574.  *    The function can convert between any combination of 1 and 2 byte
  575.  *    per pixel formats on input and output.
  576.  *
  577.  * Parameters: 
  578.  *    rleBuf (I) - input RLE compressed buffer
  579.  *    ibpp (I) - input bytes per pixel
  580.  *    expBuf (O) - output expanded buffer
  581.  *    obpp (I) - output bytes per pixel
  582.  *
  583.  * Return: none
  584.  *
  585.  **************************************************************************/
  586.  
  587. /* RLE expansion macro */
  588. /*    The algorithm here is an adaptive RLE encoding. If the run
  589.     starts with a negative count then we simply read absolute that
  590.     count pixels. If the value is positive we duplicate the pixel
  591.     count times. A zero count terminates the line.
  592. */
  593.  
  594. #define EXPAND_RLE    while (1) {                \
  595.                 pixel = *iptr++;            \
  596.                 if (!(count = (pixel & 0x7f)))    \
  597.                 return;                \
  598.                 if (pixel & 0x80) {            \
  599.                 while (count--)            \
  600.                     *optr++ = *iptr++;        \
  601.                 } else {                \
  602.                 pixel = *iptr++;        \
  603.                 while (count--)            \
  604.                     *optr++ = pixel;        \
  605.                 }                    \
  606.             }
  607.  
  608. static void rleExpandRow(short *rleBuf, int ibpp, short *expBuf, int obpp)
  609. {
  610.     register short pixel, count;
  611.  
  612.     /*
  613.      * We declare the buffer pointers according to the
  614.      * specified ibpp and obpp
  615.      */
  616.     if (ibpp == 1) {
  617.     register uchar_t *iptr = (uchar_t*)rleBuf;
  618.     if (obpp == 1) {        /* ibpp == 1, obpp == 1 */
  619.         register uchar_t *optr = (uchar_t*)expBuf;
  620.         /* CONSTCOND */
  621.         /* LINTED */
  622.         EXPAND_RLE;
  623.     } else {            /* ibpp == 1, obpp == 2 */
  624.         register short *optr = expBuf;
  625.         /* CONSTCOND */
  626.         EXPAND_RLE;
  627.     }
  628.     } else {
  629.     register short *iptr = rleBuf;
  630.     if (obpp == 1) {        /* ibpp == 2, obpp == 1 */
  631.         register uchar_t *optr = (uchar_t*)expBuf;
  632.         /* CONSTCOND */
  633.         /* LINTED */
  634.         EXPAND_RLE;
  635.     } else {            /* ibpp == 2, obpp == 2 */
  636.         register short *optr = expBuf;
  637.         /* CONSTCOND */
  638.         EXPAND_RLE;
  639.     }
  640.     }
  641. }
  642.  
  643.  
  644. /**************************************************************************
  645.  *
  646.  * Function: rleCompactRow
  647.  *
  648.  * Description: Performs an adaptive RLE compression on the specified data.
  649.  *    The function can convert between any combination of 1 and 2 byte
  650.  *    per pixel formats on input and output.
  651.  *
  652.  * Parameters: 
  653.  *    expBuf (O) - input uncompacted buffer
  654.  *    ibpp (I) - input bytes per pixel
  655.  *    rleBuf (I) - output RLE compressed buffer
  656.  *    obpp (I) - output bytes per pixel
  657.  *    npixels (I) - number of pixels in row
  658.  *
  659.  * Return: Size in bytes of the compacted row.
  660.  *
  661.  **************************************************************************/
  662.  
  663. /* RLE compression macro */
  664. /*    The algorithm here is an adaptive RLE encoding. If the run
  665.     starts with a negative count then we simply read absolute that
  666.     count pixels. If the value is positive we duplicate the pixel
  667.     count times. A zero count terminates the line.
  668. */
  669.  
  670. #define COMPACT_RLE    while (iptr < ibufend) {            \
  671.                 sptr = iptr;                \
  672.                 iptr += 2;                    \
  673.                 while ((iptr < ibufend) &&            \
  674.                    ((iptr[-2] != iptr[-1]) ||        \
  675.                     (iptr[-1] != iptr[0])))        \
  676.                 iptr++;                    \
  677.                 iptr -= 2;                    \
  678.                 count = iptr - sptr;            \
  679.                 while (count) {                \
  680.                 todo = (count > 126)? 126: count;    \
  681.                 count -= todo;                \
  682.                 *optr++ = 0x80 | todo;            \
  683.                 while (todo--)                \
  684.                     *optr++ = *sptr++;            \
  685.                 }                        \
  686.                 sptr = iptr;                \
  687.                 cc = *iptr++;                \
  688.                 while ((iptr < ibufend) && (*iptr == cc))    \
  689.                 iptr++;                    \
  690.                 count = iptr - sptr;            \
  691.                 while (count) {                \
  692.                 todo = (count > 126)? 126: count;    \
  693.                 count -= todo;                \
  694.                 *optr++ = todo;                \
  695.                 *optr++ = cc;                \
  696.                 }                        \
  697.             }                        \
  698.             *optr++ = 0;
  699.  
  700. static int rleCompactRow(short *expBuf, int ibpp, short *rleBuf, int obpp,
  701.                                 int npixels)
  702. {
  703.     register short todo, cc;
  704.     register long count;
  705.  
  706.     /*
  707.      * We declare the buffer pointers according to the
  708.      * specified ibpp and obpp
  709.      */
  710.     if (ibpp == 1 && obpp == 1) {
  711.     register uchar_t *iptr = (uchar_t*)expBuf;
  712.     register uchar_t *ibufend = iptr + npixels;
  713.     register uchar_t *sptr;
  714.     register uchar_t *optr = (uchar_t*)rleBuf;
  715.     /* LINTED */
  716.     COMPACT_RLE;
  717.     return optr - (uchar_t*)rleBuf;
  718.     }
  719.     if (ibpp == 1 && obpp == 2) {
  720.     register uchar_t *iptr = (uchar_t*)expBuf;
  721.     register uchar_t *ibufend = iptr + npixels;
  722.     register uchar_t *sptr;
  723.     register short *optr = rleBuf;
  724.     /* LINTED */
  725.     COMPACT_RLE;
  726.     return optr - rleBuf;
  727.     }
  728.     if (ibpp == 2 && obpp == 1) {
  729.     register short *iptr = expBuf;
  730.     register short *ibufend = iptr + npixels;
  731.     register short *sptr;
  732.     register uchar_t *optr = (uchar_t*)rleBuf;
  733.     /* LINTED */
  734.     COMPACT_RLE;
  735.     return optr - (uchar_t*)rleBuf;
  736.     }
  737.     {    /* ibpp == 2 && obpp == 2 */
  738.     register short *iptr = expBuf;
  739.     register short *ibufend = iptr + npixels;
  740.     register short *sptr;
  741.     register short *optr = rleBuf;
  742.     /* LINTED */
  743.     COMPACT_RLE;
  744.     return optr - rleBuf;
  745.     }
  746. }
  747.